package com.cugmarket.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cugmarket.constant.MessageConstant;
import com.cugmarket.dto.ProductInfoDocDTO;
import com.cugmarket.dto.UserDTO;
import com.cugmarket.entity.ProductCollect;
import com.cugmarket.entity.ProductInfo;
import com.cugmarket.entity.User;
import com.cugmarket.exception.BaseException;
import com.cugmarket.mapper.ProductInfoMapper;
import com.cugmarket.mapper.UserMapper;
import com.cugmarket.service.ProductCollectService;
import com.cugmarket.service.ProductInfoService;
import com.cugmarket.service.UserService;
import com.cugmarket.vo.PageVO;
import com.cugmarket.vo.ProductInfoVO;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.cugmarket.constant.MessageConstant.IS_EMPTY;
import static com.cugmarket.constant.SystemConstants.*;

@Slf4j
@Service
public class ProductInfoServiceImpl extends ServiceImpl<ProductInfoMapper, ProductInfo> implements ProductInfoService {

    @Resource
    private ProductInfoMapper productInfoMapper;
    @Resource
    private ProductCollectService productCollectService;
    @Resource
    private UserService userService;
    @Autowired
    private UserMapper userMapper;

    private RestHighLevelClient client;

    @Autowired
    public ProductInfoServiceImpl(RestHighLevelClient client) {
        this.client = client;
    }

//    @PreDestroy
//    public void closeClient() throws IOException {
//        if (client != null) {
//            client.close();
//        }
//    }

    /**
     * currentPage从1 开始查询
     *
     * @param currentPage
     * @param pageSize
     * @return
     */
    @Override
    public PageVO selectList(Integer currentPage, Integer pageSize) {
        PageHelper.startPage(currentPage, pageSize);
        // 执行分页查询
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(ProductInfo::getCreateTime);
        List<ProductInfo> productInfos = productInfoMapper.selectList(queryWrapper);

        // 收集所有用户ID
        Set<String> userIds = productInfos.stream()
                .map(ProductInfo::getUserId)
                .collect(Collectors.toSet());

        // 一次性获取所有用户信息，并存储在Map中
        Map<String, UserDTO> userMap = userIds.stream()
                .collect(Collectors.toMap(Function.identity(), userService::getUserById));

        List<ProductInfoVO> productInfoVOList = new ArrayList<>();
        for (ProductInfo productInfo : productInfos) {
            String userId = productInfo.getUserId();
            UserDTO user = userMap.get(userId);
            if (user != null && user.getAvatar() != null) {
                ProductInfoVO productInfoVO = new ProductInfoVO();
                BeanUtil.copyProperties(productInfo, productInfoVO);
                productInfoVO.setAvatar(user.getAvatar());
                productInfoVO.setNickName(user.getNickName());
                productInfoVOList.add(productInfoVO);
            }
        }
        // 使用 PageInfo 获取分页的元数据
        PageInfo<ProductInfoVO> pageInfo = new PageInfo<>(productInfoVOList);
        // 构建 PageVO 对象并返回
        PageVO pageVO = new PageVO();
        pageVO.setTotal(pageInfo.getTotal()); // 总记录数
        pageVO.setRecords(pageInfo.getList()); // 当前页数据

        return pageVO;
    }

    /**
     * 根据类型进行分页查询
     *
     * @param currentPage 当前页码，从1开始
     * @param pageSize    每页记录数
     * @param typeId      类型ID
     * @return 分页结果
     */
    @Override
    public PageVO selectListByType(Integer currentPage, Integer pageSize, String typeId) {
        PageHelper.startPage(currentPage, pageSize);

        // 根据 typeId 进行条件查询，若 typeId 为空，则返回所有
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductInfo::getTypeId, typeId)
                .orderByDesc(ProductInfo::getCreateTime);
        List<ProductInfo> productInfos = productInfoMapper.selectList(queryWrapper);

        // 收集所有用户ID
        Set<String> userIds = productInfos.stream()
                .map(ProductInfo::getUserId)
                .collect(Collectors.toSet());

        // 一次性获取所有用户信息，并存储在Map中
        Map<String, UserDTO> userMap = userIds.stream()
                .collect(Collectors.toMap(Function.identity(), userService::getUserById));

        // 构建 ProductInfoVO 列表并填充用户信息
        List<ProductInfoVO> productInfoVOList = new ArrayList<>();
        for (ProductInfo productInfo : productInfos) {
            String userId = productInfo.getUserId();
            UserDTO user = userMap.get(userId);
            if (user != null && user.getAvatar() != null) {
                ProductInfoVO productInfoVO = new ProductInfoVO();
                BeanUtil.copyProperties(productInfo, productInfoVO);
                productInfoVO.setAvatar(user.getAvatar());
                productInfoVO.setNickName(user.getNickName());
                productInfoVOList.add(productInfoVO);
            }
        }

        // 使用 PageInfo 获取分页元数据
        PageInfo<ProductInfoVO> pageInfo = new PageInfo<>(productInfoVOList);

        // 构建 PageVO 对象并返回
        PageVO pageVO = new PageVO();
        pageVO.setTotal(pageInfo.getTotal()); // 总记录数
        pageVO.setRecords(pageInfo.getList()); // 当前页数据

        return pageVO;
    }

    /**
     * 根据地区编码进行分页查询
     *
     * @param currentPage 当前页码，从1开始
     * @param pageSize    每页记录数
     * @param adCode      地区编码
     * @return 分页结果
     */
    @Override
    public PageVO selectListByAdCode(Integer currentPage, Integer pageSize, String adCode) {
        PageHelper.startPage(currentPage, pageSize);
        // 根据 adCode 进行条件查询
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.likeRight(ProductInfo::getAdcode, adCode)
                .orderByDesc(ProductInfo::getCreateTime);
        List<ProductInfo> productInfos = productInfoMapper.selectList(queryWrapper);
        // 收集所有用户ID
        Set<String> userIds = productInfos.stream()
                .map(ProductInfo::getUserId)
                .collect(Collectors.toSet());

        // 一次性获取所有用户信息，并存储在Map中
        Map<String, UserDTO> userMap = userIds.stream()
                .collect(Collectors.toMap(Function.identity(), userService::getUserById));

        // 构建 ProductInfoVO 列表并填充用户信息
        List<ProductInfoVO> productInfoVOList = new ArrayList<>();
        for (ProductInfo productInfo : productInfos) {
            String userId = productInfo.getUserId();
            UserDTO user = userMap.get(userId);
            if (user != null && user.getAvatar() != null) {
                ProductInfoVO productInfoVO = new ProductInfoVO();
                BeanUtil.copyProperties(productInfo, productInfoVO);
                productInfoVO.setAvatar(user.getAvatar());
                productInfoVO.setNickName(user.getNickName());
                productInfoVOList.add(productInfoVO);
            }
        }
        // 使用 PageInfo 获取分页元数据
        PageInfo<ProductInfoVO> pageInfo = new PageInfo<>(productInfoVOList);

        // 构建 PageVO 对象并返回
        PageVO pageVO = new PageVO();
        pageVO.setTotal(pageInfo.getTotal()); // 总记录数
        pageVO.setRecords(pageInfo.getList()); // 当前页数据
        return pageVO;
    }

    @Override
    public PageVO selectListByUserIdPublish(Integer currentPage, Integer pageSize, String userId) {
        // 启动分页
        PageHelper.startPage(currentPage, pageSize);

        // 根据 userId 进行条件查询:审核中3，审核失败6，已上线9
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductInfo::getUserId, userId)
                .and(wrapper -> wrapper.eq(ProductInfo::getStatus, MessageConstant.PRODUCT_PUBLISHED)
                        .or()
                        .eq(ProductInfo::getStatus, MessageConstant.PRODUCT_CHECK)
                        .or()
                        .eq(ProductInfo::getStatus, MessageConstant.PRODUCT_CHECK_FAILURE))
                .orderByDesc(ProductInfo::getCreateTime);

        return getPageVO(queryWrapper, userId);
    }

    @Override
    public PageVO selectListByUserIdSold(Integer currentPage, Integer pageSize, String userId) {
        // 启动分页
        PageHelper.startPage(currentPage, pageSize);

        // 根据 userId 进行条件查询：交易中10和已卖出12的
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProductInfo::getUserId, userId)
                .and(wrapper -> wrapper.eq(ProductInfo::getStatus, MessageConstant.PRODUCT_SOLD)
                        .or()
                        .eq(ProductInfo::getStatus, MessageConstant.PRODUCT_TRADING))
                .orderByDesc(ProductInfo::getCreateTime);
        return getPageVO(queryWrapper, userId);
    }

    @Override
    public PageVO selectListByUserIdCollect(Integer currentPage, Integer pageSize, String userId) {
        // 启动分页
        PageHelper.startPage(currentPage, pageSize);
        List<ProductCollect> productCollects = productCollectService.getPCByUserId(userId);
        if (productCollects.isEmpty()) {
            throw new BaseException(IS_EMPTY);
        }
        // 从 productCollects 集合中提取出所有商品的 ID
        List<String> productIds = productCollects.stream()
                .map(ProductCollect::getProductId) // 假设 ProductCollect 类中有 getProductId 方法
                .collect(Collectors.toList());
        // 根据 productId 进行条件查询
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProductInfo::getId, productIds)
                .orderByDesc(ProductInfo::getCreateTime);

        return getPageVO(queryWrapper, userId);
    }

    /**
     * 根据商品ID获取商品详情
     *
     * @param id
     * @return
     */
    @Override
    public ProductInfoVO getByProductId(String id) {
        // 根据id查询商品信息
        ProductInfo productInfo = productInfoMapper.selectById(id);
        // 根据productInfo的userId查询对应用户的头像和昵称
        String userId = productInfo.getUserId();
        // 查询商品发布者的信息
        UserDTO user = userService.getUserById(userId);
        // 将商品信息转换为 ProductInfoVO 对象
        ProductInfoVO productInfoVO = new ProductInfoVO();
        BeanUtil.copyProperties(productInfo, productInfoVO);
        // 设置用户头像和昵称
        productInfoVO.setAvatar(user.getAvatar());
        productInfoVO.setNickName(user.getNickName());
        return productInfoVO;
    }

    /**
     * 根据条件搜索
     * @param condition
     * @return
     */
    @Override
    public PageVO getProductByCondition(Integer currentPage, Integer pageSize, String condition) throws IOException {
        PageHelper.startPage(currentPage, pageSize);
        // 1.创建Request
        SearchRequest request = new SearchRequest(ES_INDEXNAME);
        // 2.组织请求参数
        // 2.1.准备bool查询
        BoolQueryBuilder bool = QueryBuilders.boolQuery();
        // 2.2.标题和介绍搜索
        bool.should(QueryBuilders.matchQuery(ES_MATCHQUERY_TITLE, condition));
        bool.should(QueryBuilders.matchQuery(ES_MATCHQUERY_INTRO, condition));
        // 设置should查询至少匹配一个条件
        bool.minimumShouldMatch(1);
//        // 2.3.送货类型过滤
//        bool.filter(QueryBuilders.termQuery("postType", 1));
//        // 2.4.价格过滤
//        bool.filter(QueryBuilders.rangeQuery("price").gte(1).lte(120));
        request.source().query(bool);
//          默认按照枫分数排序
//        request.source().sort("price", SortOrder.ASC);
        // 2.5.分页
        request.source().from(ES_MIN_QUERYSIZE).size(ES_MAX_QUERYSIZE);
        // 2.6.高亮条件
        request.source().highlighter(
                SearchSourceBuilder.highlight()
                        .field(ES_MATCHQUERY_TITLE)
                        .field(ES_MATCHQUERY_INTRO)
                        .preTags("<em>")
                        .postTags("</em>")
        );
        // 3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 4.解析响应
        PageVO pageVO = handleResponse(response);
        return pageVO;
    }

    private PageVO handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        // 1.获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        // 2.遍历结果数组
        SearchHit[] hits = searchHits.getHits();
        List<ProductInfoDocDTO> productInfoDocDTOList = new ArrayList<>();
        for (SearchHit hit : hits) {
            // 3.得到_source，也就是原始json文档
            String source = hit.getSourceAsString();
            // 4.反序列化并打印
            ProductInfoDocDTO productInfoDoc = JSONUtil.toBean(source, ProductInfoDocDTO.class);
            // 5.获取高亮结果
            Map<String, HighlightField> hfs = hit.getHighlightFields();
            if (!hfs.isEmpty()) {
                // 5.1.遍历所有高亮字段
                for (Map.Entry<String, HighlightField> entry : hfs.entrySet()) {
                    String fieldName = entry.getKey();
                    HighlightField hf = entry.getValue();
                    // 5.2.检查高亮字段是否是title或intro
                    if (ES_MATCHQUERY_TITLE.equals(fieldName) || ES_MATCHQUERY_INTRO.equals(fieldName)) {
                        // 5.3.获取第一个高亮结果片段
                        String hfFragment = hf.getFragments()[0].string();
                        // 5.4.根据字段名设置到相应的属性中
                        if (ES_MATCHQUERY_TITLE.equals(fieldName)) {
                            productInfoDoc.setTitle(hfFragment);
                        } else {
                            productInfoDoc.setIntro(hfFragment);
                        }
                    }
                }
            }
            productInfoDocDTOList.add(productInfoDoc);
        }
        if (productInfoDocDTOList.isEmpty()) {
            throw new BaseException(IS_EMPTY);
        }
        // 从 productCollects 集合中提取出所有商品的 ID
        List<String> productIds = productInfoDocDTOList.stream()
                .map(ProductInfoDocDTO::getId) // 假设 ProductCollect 类中有 getProductId 方法
                .collect(Collectors.toList());
        // 根据 productId 进行条件查询
        LambdaQueryWrapper<ProductInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProductInfo::getId, productIds);
        PageHelper.clearPage();
        List<ProductInfo> productInfos = productInfoMapper.selectList(queryWrapper);

        Set<String> userIds = productInfos.stream()
                .map(ProductInfo::getUserId)
                .collect(Collectors.toSet());
        // 一次性获取所有用户信息，并存储在Map中
        Map<String, UserDTO> userMap = userIds.stream()
                .collect(Collectors.toMap(Function.identity(), userService::getUserById));

        // 构建 ProductInfoVO 列表并填充用户信息
        List<ProductInfoVO> productInfoVOList = new ArrayList<>();
        for (int i = 0; i < productInfos.size(); i++) {
            ProductInfo productInfo = productInfos.get(i);
            ProductInfoDocDTO productInfoDocDTO = productInfoDocDTOList.get(i);
            BeanUtil.copyProperties(productInfoDocDTO, productInfo);
            String userId = productInfo.getUserId();
            UserDTO user = userMap.get(userId);
            if (user != null && user.getAvatar() != null) {
                ProductInfoVO productInfoVO = new ProductInfoVO();
                BeanUtil.copyProperties(productInfo, productInfoVO);
                productInfoVO.setAvatar(user.getAvatar());
                productInfoVO.setNickName(user.getNickName());
                productInfoVOList.add(productInfoVO);
            }
        }
        // 使用 PageHelper 获取分页元数据
        PageInfo<ProductInfo> pageInfo = new PageInfo<>(productInfos);
        PageVO pageVO = new PageVO();
        // 构建 PageVO 对象并返回
        pageVO.setTotal(pageInfo.getTotal()); // 总记录数
        pageVO.setRecords(productInfoVOList); // 当前页数据
        return pageVO;
    }

    private PageVO getPageVO(LambdaQueryWrapper<ProductInfo> queryWrapper, String userId) {
        List<ProductInfo> productInfos = productInfoMapper.selectList(queryWrapper);
        // 查询用户信息（只需查询一次）
        User user = userMapper.selectById(userId);

        // 将商品信息转换为 ProductInfoVO 对象
        List<ProductInfoVO> productInfoVOList = new ArrayList<>();
        for (ProductInfo productInfo : productInfos) {
            ProductInfoVO productInfoVO = new ProductInfoVO();
            // 将商品信息拷贝进VO对象
            BeanUtil.copyProperties(productInfo, productInfoVO);
            // 填充用户信息到VO对象
            productInfoVO.setAvatar(user.getAvatar());
            productInfoVO.setNickName(user.getNickName());
            productInfoVOList.add(productInfoVO);
        }
        // 使用 PageHelper 获取分页元数据
        PageInfo<ProductInfo> pageInfo = new PageInfo<>(productInfos);
        PageVO pageVO = new PageVO();
        // 构建 PageVO 对象并返回
        pageVO.setTotal(pageInfo.getTotal()); // 总记录数
        pageVO.setRecords(productInfoVOList); // 当前页数据
        return pageVO;
    }

}
